''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'Weather station Test 3                                                                 '
''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''

'Constants
Const swVer = "0.1"
Const wSpeedPin = 6                              'Wind speed sensor
Const RainPin = 14                               'Rain sensor
Const wDirPin = 26                               'Direction sensor
Const WindFactor = 0.4166666666666667            'unique to each enenemeter type 
Const RainFactor = 0.2794                        'mm rain for every switch closure
Const TestPause = 3000                           'Wind speed sample time
SETPIN 23, DOUT                               'GPS Power
SETPIN 16, DOUT                               'GPS Power
'Define I/O
Setpin wSpeedPin,Intl,anemometerClick,Pullup
Setpin RainPin,Intl,rainguageClick,Pullup
SETPIN 26, AIN                                'wind speed sensor
'  BME280 routines and test harness   
'   
const BME280_ADDRESS                    = &H77   
const BME280_REGISTER_T1                = &H88   
const BME280_REGISTER_P1                = &H8E   
const BME280_REGISTER_H1                = &HA1   
const BME280_REGISTER_H2                = &HE1   
const BME280_REGISTER_CHIPID            = &HD0   
const BME280_REGISTER_CONTROLHUMID      = &HF2   
const BME280_REGISTER_CONTROL           = &HF4   
const BME280_REGISTER_PRESSUREDATA      = &HF7   
const BME280_REGISTER_TEMPDATA          = &HFA   
const BME280_REGISTER_HUMIDDATA         = &HFD   
'   
dim integer s16=&HFFFFFFFFFFFF0000 , s16b=&H8000 
dim integer s12=&HFFFFFFFFFFFFF000 , s12b=&H800 
dim integer s8= &HFFFFFFFFFFFFFF00  , s8b=&H80 
'          
DIM INTEGER T1,T2,T3     'uint16_t, int16_t, int16_t    
DIM INTEGER P1,P2,P3,P4,P5,P6,P7,P8,P9    'uint16_t, 8 x int16_t    
DIM INTEGER H1,H2,H3,H4,H5,H6     'uint8_t, int16_t , uint8_t, int16_t, int16_t, int8_t    
' 
dim INTEGER t_fine  'used to store accurate temp reading from temp conversion for use in pressure and humidity conversions
'   

' Global variables
dim anem_count,anem_last,wspeed,wcount
dim anem_min=1000
dim Wgust
dim thistime as integer
Dim rain_count
DIM mmrain,wdir,rain_last
 ' Array 
Dim wArray(10) 
Dim wdArray(10) 
  
  anem_count=0 
  anem_last=0 
  anem_min=1000 
  HGust=0 
  rain_count=0 
  rain_last=0 
  wCount=1 
  wdCount=1 
'******************************************************************************************************************
Init:

'interupts
Settick 1000 ,L1,1                                    'establish seconds "Tick Timer"
PIN(23) = 1                                 'GPS Power OFF
PIN(16) = 1                                 'GPS Power OFF


' ******************this is the main program loop, it never exits ******************************




Do 
 
if secs  mod 5 = 0 then  'every 5 secs 
 windSpeedProc
 WindDirProc
 rainProc
  End if 

if secs  mod 10 = 0 then  'every 10 secs 
  bme280_init 
  End if
  
if secs  mod 20 = 0 then   'every 20 secs 
  SendDataUpdate
   'Print "Outside Temperature: "
  'Print "Outside Humidity: "
  End if
 
'Select Case mins 

 'Case 5,10,15,20,25,30,35,40,45,50,55,60 
 'Print "5 mins_ Sending Data Update" 
 'SendDataUpdate 
 'End Select 

loop
End

'***** End main program loop*************************************************************************************

'Sub routines
'rainguage sensor interrupt
Sub rainguageClick
thistime=Timer-rain_last
rain_last=Timer
If thistime>10 Then
  rain_count=rain_count+1
  'Print "Rain click"
End If
End Sub

'***********************************************************************************

'Wind speed sensor interrupt
Sub anemometerClick
thistime=Timer-anem_last  'thistime measures the time between pulses
anem_last=Timer
If thistime>5 Then                     'only process if > 5mSec, for switch debounce
  anem_count=anem_count+1              'Adds up pulses single pulse per/rotation
  'anem_count=anem_count+3              'Adds up pulses  '****similation for 3 pulses only - Rem when not used ****
  If thistime<anem_min Then            'If the time is less than 1 second
    anem_min=thistime 'gust            'then thistime = gust
  End If
  'Print "Wind click"               'Prints this EVERY time the reed switch closes=**TEST USE ONLY - DELETE WHEN happy its working properly
  'use this to check how many switch closures per revolution when turning by hand
end if
'print "Incr Anem counts:";anem_count;" This Pulse interval:";thistime;" Min Pulse interval:";anem_min ***While testing only***
End Sub


'************************************************************************************
'Wind Direction data process           ** Checked with multimeter 0-3.3v 0-360 deg*****
Sub WindDirProc
value=pin(26)
select case value 
  CASE 0.0 to 0.103125                       ' 0.00916666666666666666666666666667V per degree
   Wheading$ = "North" 
 case 0.103126 to 0.309375
  wheading$ = "NNE"
 case 0.309376 to 0.515625
  wheading$ = "NE" 
 case 0.515626 to 0.721875 
  wheading$ = "East"
 case 0.721876 to 0.928125 
  wheading$ = "ESE"  
 case 0.928126 to 1.134375
  wheading$ = "ESE" 
 case 1.134376 to 1.340625
   wheading$ = "SEast"  
 case 1.340626 to 1.56875
  wheading$ = "SSE" 
 case 1.56876 to 1.753125
  wheading$ = "South"
 case 1.753126 to 1.959375 
  wheading$ = "SSw"    
 case 1.959376 to 2.165625
  wheading$ = "SWest" 
 case 2.165626 to 2.371875
  wheading$ = "WSE"     
 case 2.371876 to 2.578125
  wheading$ = "West"  
 case 2.578126 to 2.784375
  wheading$ = "WNW"    
 case 2.784375 to 2.990625
  wheading$ = "NWest"    
 case 2.990626 to 3.196875  
  wheading$ = "NNW"
 CASE 3.196875 to 3.3 
  wheading$ = "North"   
 CASE ELSE 
  wheading$="not yet assigned" 
 end select 
 '***************************************************************************************
End Sub
 
'**********************************************************************************

'Wind Speed data process 
Sub WindSpeedProc 
wResult=0 
'calc wind average 
reading=anem_count 
anem_count=0 
wSpeed=(windfactor*reading)/(testpause/1000) 
'calc Gust 
reading=anem_min 
anem_min=1000 
wGust=(1/(reading/1000))*windfactor 
For x=1 To 9        'move data up array 
  wArray(x)=wArray(x+1) 
Next x 
wArray(10)=wSpeed    'place latest reading in Array 
For x=1 To 10         'addup all data in array 
  wResult=wResult+wArray(x) 
Next x 
wCount=wCount+1 
If wCount>10 Then wCount=1 
wSpeed=wResult/10           'get average the the last 10 wind samples 
If wgust>hgust Then hgust=wgust 
End Sub 


'************************************************************************************

'Rain sensor process  
Sub RainProc
reading=rain_count
rain_count=0
mmRain=mmRain + (reading*rainfactor)
End Sub

'*********************************************************************************************

Sub SendDataUpdate
'print #2, "Direction:"; wheading$ " WindSpeed: "; wspeed ;"Average Wind Speed: "; wspeed ;" Gust "; wgust ;" Highest Gust "; hgust;" Rain"; mmrain;" mm"    'Rain
print " Direction: "; wheading$ 
print " WindSpeed: "; wspeed; " MPH"
print " Gust "; wgust; " MPH"
print " Highest Gust "; hgust; " MPH"
print " Rain"; mmrain;" mm"
print " Temperature";  bme280_read_temp()" C "
print " Pressure"; bme280_read_pressure()" mB " 
PRINT " HUMIDITY"; bme280_read_humidity()" %"  
Print "*******************************"
i2c close   
pause 1000  ' pause
End Sub
 
*****************************************************************************************

' Put clock update Sub here
 
 'IF hour = 02 and if min = 05 then sync clock
'end if

'L1 - 1second Tick interrupt
Sub L1
secs=secs+1   'update seconds timer
if secs => 86400 then     '24 hrs reached
  secs = 0                'reset counter
endif


 'If Time$="02:05" Then 'Update RTC
'put clock update sub here
'Endif

 'If Time$="09:00" Then 'New Met day 
    'put code here 'sync Clock 
   ' Hgust=0 'reset High Gust 
   ' mmRainday=mmRain 
   ' mmRain=0  'reset Rain 
   ' Endif 
'end if 

'If mins>60 Then 'reset after 1 min 
 ' mins=0 
'End If 

End Sub 


'*************************************************************************************************** 
'   
function  bme280_read_temp() as float   
  local integer var1,var2,adc_T   
  local adc%(2)   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_TEMPDATA   
  i2c read BME280_ADDRESS,0,3,adc%()   
  adc_T=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4   
  var1  = ((((adc_T>>3) - (T1 <<1))) * T2) \ q(11)   
  var2  = (((((adc_T>>4) - (T1)) * ((adc_T\ q(4)) - (T1))) \ q(12)) * (T3)) \ q(14)   
  t_fine = var1 + var2   
  bme280_read_temp = ((t_fine * 5 + 128) \ q(8))/100.0   
end function   

function  bme280_read_pressure() as float   
  local integer var1, var2, adc_P, p   
  local adc%(2)   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_PRESSUREDATA   
  i2c read BME280_ADDRESS,0,3,adc%()   
  adc_P=((adc%(0)<<16) OR (adc%(1)<<8) or adc%(2))>>4   
  var1 = t_fine - 128000   
  var2 = var1 * var1 * P6   
  var2 = var2 + ((var1 * P5)<<17)   
  var2 = var2 + (P4 << 35)   
  var1 = ((var1 * var1 * P3)\ q(8)) +    ((var1 * P2)<<12)   
  var1 = ((1<<47)+var1)*P1\ q(33)   
  if var1 = 0 THEN   
    bme280_read_pressure =  0' avoid exception caused by division by zero   
    exit function   
  endif   
  p = 1048576 - adc_P   
  p = (((p<<31) - var2)*3125) \ var1   
  var1 = (P9 * (p\ q(13)) * (p\ q(13))) \ q(25)   
  var2 = (P8 * p) \ q(19)   
  p = ((p + var1 + var2) \ q(8)) + (P7<<4)   
  bme280_read_pressure = p/25600.0   
end function   
'   
function  bme280_read_humidity() as float   
  local integer v_x1,adc_H   
  local adc%(1)   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_HUMIDDATA   
  i2c read BME280_ADDRESS,0,2,adc%()   
  adc_H=(adc%(0)<<8) or adc%(1)   
  v_x1 = t_fine - 76800   
  v_x1=(((((adc_H<<14)-((H4)<<20)-(H5*v_x1))+16384)\ q(15))*(((((((v_x1*H6)\ q(10))*(((v_x1*H3)\ q(11))+32768))\ q(10))+2097152)*H2+8192)\ q(14)))   
  v_x1 = (v_x1 - (((((v_x1 \ q(15)) * (v_x1 \ q(15))) \ q(7)) * (H1)) \ q(4)))   
  if v_x1< 0 then v_x1 = 0   
  if v_x1 > 419430400 then v_x1= 419430400   
  bme280_read_humidity = (v_x1\ q(12)) / 1024.0   
end function   

sub bme280_init   
  local i%,cal%(17)   
  i2c open 400,1000 '400KHz bus speed   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_CHIPID   
  i2c read BME280_ADDRESS,0,1,i%   
  if i%<>&H60 then print "Error BME280 not found"   
   if i%<>&H60 then print #7, "Error BME280 not found" 
  '   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_T1   
  i2c read BME280_ADDRESS,0,6,cal%()   
  T1=cal%(0) OR (cal%(1)<< 8)   
  T2=cal%(2) OR (cal%(3)<< 8):   if T2 and s16b then T2=T2 OR s16 'sign extend if required   
  T3=cal%(4) OR (cal%(5)<< 8):   if T3 and s16b then T3=T3 OR s16  
  '   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_P1   
  i2c read BME280_ADDRESS,0,18,cal%()   
  P1=cal%(0) OR (cal%(1)<<8)   
  P2=cal%(2) OR (cal%(3)<<8):   if P2 and s16b then P2=P2 OR s16 'sign extend if required   
  P3=cal%(4) OR (cal%(5)<<8):   if P3 and s16b then P3=P3 OR s16 
  P4=cal%(6) OR (cal%(7)<<8):   if P4 and s16b then P4=P4 OR s16  
  P5=cal%(8) OR (cal%(9)<<8):   if P5 and s16b then P5=P5 OR s16 
  P6=cal%(10) OR (cal%(11)<<8):   if P6 and s16b then P6=P6 OR s16 
  P7=cal%(12) OR (cal%(13)<<8):   if P7 and s16b then P7=P7 OR s16 
  P8=cal%(14) OR (cal%(15)<<8):   if P8 and s16b then P8=P8 OR s16 
  P9=cal%(16) OR (cal%(17)<<8):   if P9 and s16b then P9=P9 OR s16 
  '   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H1   
  i2c read BME280_ADDRESS,0,1,H1   
  i2c write BME280_ADDRESS,1,1,BME280_REGISTER_H2   
  i2c read BME280_ADDRESS,0,7,cal%()   
  H2=cal%(0) OR (cal%(1)<< 8):   if H2 and s16b then H2=H2 OR s16 'sign extend if required   
  H3=cal%(2)   
  H6=cal%(6):   if H6 and s8b then H6=H6 OR s8 'sign extend if required   
  H4=(cal%(3)<<4) OR (cal%(4) and &H0F): if H4 and s12b then H4=H4 OR s12 'sign extend if required   
  H5=(cal%(5)<<4) OR (cal%(4)>>4):  if H5 and s12b then H5=H5 OR s12 
  '   
  i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROLHUMID,&H05 '16x oversampling humidity 
  i2c write BME280_ADDRESS,0,2,BME280_REGISTER_CONTROL,&HB7      '16x oversampling pressure/temp, normal mode    
  '   
end sub   
' 
function q(x as integer) as integer  'returns 2 raised to the power   
  q=(1<<x)   
End Function